/**
 * @file 数组相关api
 */

/**
 * 数组去重 - 普通
 * @param {array} arr 去重的数组
 * @returns {array} 不影响原数组，返回过滤后的新数组
 *
 * @example
 * unique([1,2,2,3,4,3,4,7]) // => [1, 2, 3, 4, 7]
 */
export const unique = (arr: (number | string)[]): (number | string)[] => [...new Set(arr)]

/**
 * 数组去重 - 根据数组里的对象里的某个key值去重
 * @param {array} arr 要去重的数组
 * @param {string} key 要作为去重判断的key
 * @returns {array} 不影响原数组，返回过滤后的新数组
 *
 * @example
 * uniqueBy([{name:'1111'},{name:'1111'},{name:'222'}],'name') // => [{name:'1111'},{name:'222'}
 */
export const uniqueBy = <T extends object, K extends keyof T>(arr: T[], key: K): T[] => {
  return arr.filter(
    (element, index, array) => array.findIndex(row => row[key] === element[key]) === index
  )
}

/**
 * 获取数组中的最大值
 * @param {number[]} arr
 * @returns {number} 返回最大值
 *
 * @example
 *  maxNum([12,3,31,5,3]) // => 31
 */
export const maxNum = (arr: number[]): number => Math.max.apply(Math, arr)

/**
 * 获取数组中的最小值
 * @param {number[]} arr
 * @returns {number} 返回最小值
 *
 * @example
 *  minNum([12,3,31,5,3]) // => 3
 */
export const minNum = (arr: number[]): number => Math.min.apply(Math, arr)

/**
 * 打乱数组
 * @param {unknown[]} arr
 * @returns {array} 影响原数组，返回打乱后的数组
 *
 * @example
 * shuffle([1, 3, 5, 7, 8]) // => [7, 1, 5, 8, 3]
 */
export const shuffle = <T>(arr: T[]): T[] => {
  let i = arr.length
  while (i) {
    let j = Math.floor(Math.random() * i--)
    ;[arr[j], arr[i]] = [arr[i], arr[j]]
  }
  return arr
}
